home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / fix.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  9KB  |  460 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    fix.c
  12.  *
  13.  *    Motorola has is not consistent in what operations allow
  14.  *    which operands.  This section compensates for that --
  15.  *    tries to find the best way to do something.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "nodes.h"
  21. #include "flags.h"
  22. #include "bstok.h"
  23. #include "gen.h"
  24. #include "ops.h"
  25.  
  26. #define FAIL 0
  27. #define OKAY 1
  28.  
  29. #define CL_IMM    IOPD
  30. #define CL_AREG    AOPD
  31. #define CL_DREG DOPD
  32. #define CL_ADR    MOPD
  33.  
  34. #define RETAREG    0x100
  35. #define RETDREG 0x200
  36. #define RETLEFT    0x400
  37. #define RETRIGHT 0x800
  38.  
  39. #define LISTMP    1
  40. #define RISTMP    2
  41. #define NDASSOC    4
  42. #define CANRL    8
  43. #define CANLR    0x10
  44. #define CANRD    0x20
  45. #define CANDL    0x40
  46. #define CANLD    0x80
  47. #define CANDD    0x100
  48. #define CANDR    0x200
  49.  
  50. struct mtbl {
  51.     int restr;
  52.     char *code;
  53.     int needregs;
  54. } tbl2[] = {
  55.     {LISTMP|CANRL,
  56.         "\tN.S\t>A,<A\n", RETLEFT},
  57.     {RISTMP|CANLR|NDASSOC,
  58.         "\tN.S\t<A,>A\n", RETRIGHT},
  59.     {CANRD,
  60.         "\tmove.S\t<A,A\n\tN.S\t>A,A\n", RETDREG},
  61.     {CANLD|NDASSOC,
  62.         "\tmove.S\t>A,A\n\tN.S\t<A,A\n", RETDREG},
  63.     /* only EOR and shifts get to here */
  64.     {CANDL|LISTMP,
  65.         "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", RETLEFT|1},
  66.     {CANDR|RISTMP|NDASSOC,
  67.         "\tmove.S\t<A,R1\n\tN.S\tR1,A\n", RETRIGHT|1},
  68.     {CANDD,
  69.         "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n",
  70.             RETDREG|1},
  71.     {0}
  72. };
  73.  
  74. struct mtbl tblmul[] = {
  75.     {CANRL|LISTMP,
  76.         "\tmulU\t>A,<A\n", RETLEFT},
  77.     {CANLR|RISTMP,
  78.         "\tmulU\t<A,>A\n", RETRIGHT},
  79.     {CANRD,
  80.         "\tmove.w\t>A,A\n\tmulU\t<A,A\n", RETDREG},
  81.     {0}
  82. };
  83.  
  84. struct mtbl tbldiv[] = {
  85.     {CANRL|LISTMP,
  86.         "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
  87.     {CANRD,
  88.         "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n", RETDREG},
  89.     {0}
  90. };
  91.  
  92. struct mtbl tbludiv[] = {
  93.     {CANRD,
  94.         "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n", RETDREG},
  95.     {0}
  96. };
  97.  
  98. struct mtbl tblc[] = {
  99.     {CANRL,
  100.         "\tcmp.<S\t>A,<A\n", 0},
  101.     {CANRD,
  102.         "\tmove.<S\t<A,R1\n\tcmp.<S\t>A,R1\n", 1},
  103. /* shouldnt get to here! */
  104.     {CANDL,
  105.         "\tmove.<S\t>A,R1\n\tcmp.<S\tR1,<A\n", 1},
  106.     {CANDD,
  107.         "\tmove.<S\t>A,R1\n\tmove.<S\t<A,R2\n\tcmp.<S\tR1,R2\n", 2},
  108.     {0}
  109. };
  110.  
  111. struct mtbl tblas[] = {
  112.     {CANRL,
  113.         "\tN.S\t>A,<A\n", RETLEFT},
  114.     {CANDL,
  115.         "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", 1|RETLEFT},
  116.     /* only MUL, DIV and shifts should get to here */
  117.     {CANRD,
  118.         "\tmove.S\t<A,A\n\tN.S\t>A,A\n\tmove.S\tA,<A\n",
  119.             RETDREG},
  120.     {CANLD|NDASSOC,
  121.         "\tmove.S\t>A,A\n\tN.S\t<A,A\n\tmove.S\tA,<A\n",
  122.             RETDREG},
  123.     {CANDD,
  124.     "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n\tmove.S\tA,<A\n",
  125.             RETDREG|1},
  126.     {0}
  127. };
  128.  
  129. struct mtbl tblamul[] = {
  130.     {CANRL,
  131.         "\tmulU\t>A,<A\n", RETLEFT},
  132.     {CANLR|RISTMP,
  133.         "\tmulU\t<A,>A\n\tmove.w\t>A,<A\n", RETRIGHT},
  134.     {CANRD,
  135.         "\tmove.w\t<A,A\n\tmulU\t>A,A\n\tmove.w\tA,<A\n", RETDREG},
  136.     {0}
  137. };
  138.  
  139. struct mtbl tbladiv[] = {
  140.     {CANRL,
  141.         "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
  142.     {CANRD,
  143.     "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tmove.w\tA,<A\n",
  144.         RETDREG},
  145.     {0}
  146. };
  147.  
  148. struct mtbl tbluadiv[] = {
  149.     {CANRD,
  150.     "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tmove.w\tA,<A\n",
  151.         RETDREG},
  152.     {0}
  153. };
  154.  
  155. struct mtbl tblamod[] = {
  156.     {CANRL,
  157.         "\text.l\t<A\n\tdivs\t>A,<A\n\tswap\t<A\n", RETLEFT},
  158.     {CANRD,
  159.   "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
  160.         RETDREG},
  161.     {0}
  162. };
  163.  
  164. struct mtbl tbluamod[] = {
  165.     {CANRD,
  166.   "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
  167.         RETDREG},
  168.     {0}
  169. };
  170.  
  171. class(np)
  172. NODEP np;
  173. {
  174.     switch (np->g_token) {
  175.     case ICON:
  176.         return CL_IMM;
  177.     case ONAME:
  178.         return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
  179.     case OREG:
  180.         return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
  181.     case PUSHER:
  182.         return CL_ADR;
  183.     case REGVAR:
  184.         if (np->g_rno < AREG)
  185.             return CL_DREG;
  186.         else
  187.             return CL_AREG;
  188.     default:
  189.         printf("Weird class ");
  190.         return CL_IMM;
  191.     }
  192. }
  193.  
  194. int canswap;
  195. NODEP matchnp;
  196.  
  197. fix_cmp(np, flags)
  198. NODEP np;
  199. {
  200.     NODEP rp = np->n_right;
  201.  
  202.     /* special stuff for ICON 0 */
  203.     if (rp->g_token == ICON && rp->g_offs == 0 &&
  204.         (rp->g_flags & IMMEDID)) {
  205.         addcode(np, "<Q");
  206.         return OKAY;
  207.     }
  208.     canswap = 0;
  209.     return fix_sub(np, flags, tblc);
  210. }
  211.  
  212. fix2ops(np, flags)
  213. NODEP np;
  214. {
  215.     canswap = flags & ASSOC;
  216.     return fix_sub(np, flags, tbl2);
  217. }
  218.  
  219. fixmul(np, flags)
  220. NODEP np;
  221. {
  222.     return fix_sub(np, flags, tblmul);
  223. }
  224.  
  225. fixdiv(np, flags)
  226. NODEP np;
  227. {
  228.     return fix_sub(np, flags, np->g_ty == ET_U ? tbludiv : tbldiv);
  229. }
  230.  
  231. fixmod(np, flags)
  232. NODEP np;
  233. {
  234.     int r;
  235.  
  236.     r = fixdiv(np, flags);
  237.     addcode(np, "\tswap\tA\n");
  238.     return r;
  239. }
  240.  
  241. fixamul(np, flags)
  242. NODEP np;
  243. {
  244.     return fix_sub(np, flags, tblamul);
  245. }
  246.  
  247. fixadiv(np, flags)
  248. NODEP np;
  249. {
  250.     return fix_sub(np, flags, np->g_ty == ET_U ? tbluadiv : tbladiv);
  251. }
  252.  
  253. fixamod(np, flags)
  254. NODEP np;
  255. {
  256.     return fix_sub(np, flags, np->g_ty == ET_U ? tbluamod : tblamod);
  257. }
  258.  
  259. fix_asn(np, flags)
  260. NODEP np;
  261. {
  262.     canswap = 0;
  263.     return fix_sub(np, flags, tblas);
  264. }
  265.  
  266. fix_sub(np, flags, tbl)
  267. register NODEP np;
  268. struct mtbl *tbl;
  269. {
  270.     NODEP lp = np->n_left, rp = np->n_right;
  271.     int lclass, rclass;
  272.     register struct mtbl *p;
  273.     int rv;
  274.  
  275.     lclass = class(lp);
  276.     rclass = class(rp);
  277.     matchnp = np;
  278.  
  279.     for (p = tbl; p->restr; p++)
  280.         if ((rv = cando(flags, p->restr, lclass, rclass))) {
  281.             dotbl(p, np);
  282.             return OKAY;
  283.         }
  284.     printf("no code table match! ");
  285.     return FAIL;
  286. }
  287.  
  288. dotbl(p, np)
  289. struct mtbl *p;
  290. NODEP np;
  291. {
  292.     register int i, k;
  293.  
  294.     if (p->needregs) {
  295.         i = p->needregs;
  296.         if (i & RETLEFT)
  297.             inherit(np);
  298.         else if (i & RETRIGHT)
  299.             rinherit(np);
  300.         else if (i & RETAREG)
  301.             retreg(np, ralloc(AREG));
  302.         else if (i & RETDREG)
  303.             retreg(np, ralloc(0));
  304.         k = i & 7;
  305.         while (k--)
  306.             tempr(np, 0);
  307.         k = (i/AREG) & 7;
  308.         while (k--)
  309.             tempr(np, AREG);
  310.     }
  311.     addcode(np, p->code);
  312. }
  313.  
  314. #define canflag(l,r)    (l << cansh[r])
  315.  
  316. short cansh[] = {0, 0, 4, 0, 8, 0, 0, 0, 12};
  317.  
  318. cando(flags, restr, lc, rc)
  319. register restr;
  320. {
  321.     NODEP lp = matchnp->n_left, rp = matchnp->n_right;
  322.  
  323.     if (restr & RISTMP) {
  324.         if ((rc & (CL_DREG|CL_AREG)) == 0 ||
  325.             istemp(rp->g_rno) == 0)
  326.             return 0;
  327.     } else if (restr & LISTMP) {
  328.         if ((lc & (CL_DREG|CL_AREG)) == 0 ||
  329.             istemp(lp->g_rno) == 0)
  330.             return 0;
  331.     }
  332.     if (restr & NDASSOC) {
  333.         if (canswap == 0)
  334.             return 0;
  335.     }
  336.     if (restr & (CANLR|CANLD)) {
  337.         flags |= quickflag(lp, flags);
  338.     } else if (restr & (CANRL|CANRD)) {
  339.         flags |= quickflag(rp, flags);
  340.     }
  341.     flags &= 0xfff;
  342.     if (restr & CANLR) {
  343.         if ((flags & canflag(lc,rc)) == 0)
  344.             return 0;
  345.     } else if (restr & CANRL) {
  346.         if ((flags & canflag(rc,lc)) == 0)
  347.             return 0;
  348.     } else if (restr & CANRD) {
  349.         if ((flags & canflag(rc,CL_DREG)) == 0)
  350.             return 0;
  351.     } else if (restr & CANDL) {
  352.         if ((flags & canflag(CL_DREG,lc)) == 0)
  353.             return 0;
  354.     } else if (restr & CANLD) {
  355.         if ((flags & canflag(lc,CL_DREG)) == 0)
  356.             return 0;
  357.     } else if (restr & CANDR) {
  358.         if ((flags & canflag(CL_DREG,rc)) == 0)
  359.             return 0;
  360.     } else if (restr & CANDD) {
  361.         if ((flags & DOPD) == 0)
  362.             return 0;
  363.     }
  364.     return 1;
  365. }
  366.  
  367. quickflag(np, flags)
  368. NODEP np;
  369. {
  370.     long offs;
  371.  
  372.     if (np->g_token != ICON)
  373.         return 0;
  374.     offs = np->g_offs;
  375.     if ((flags & QOPD) && np->g_offs >= 1 && np->g_offs <= 8)
  376.         return IOPD;
  377.     if ((flags & ONEOPM) && np->g_offs == 1)
  378.         return IOPM;
  379.     return 0;
  380. }
  381.  
  382. /*
  383.  * stuff to do field extract and field assign
  384.  * Yes, this stuff can be optimized a lot more ... feel free
  385.  */
  386. fldget(np, flags)
  387. register NODEP np;
  388. {
  389.     int how;
  390.  
  391.     how = 1;
  392.     if (np->g_fldo == 0)
  393.         how = 0;    /* no shift needed */
  394.     else if (np->g_fldo > 8)
  395.         how = 2;    /* shift too big for immediate */
  396.  
  397.     np->n_left->g_offs += np->g_offs;    /* major HACK, hope it works */
  398.  
  399.     retreg(np, ralloc(0));
  400.  
  401.     addcode(np, "\tmove\t<A,A\n");        /* get word */
  402.     if (how)                /* shift to position */
  403.         addcode(np, how==1 ?    "\tlsr\t#Y,A\n" :
  404.             "\tlsr\t#8,A\n\tlsr\t#Z,A\n");
  405.     addcode(np, "\tand\t#W,A\n");        /* mask off top */
  406.  
  407.     return OKAY;
  408. }
  409.  
  410. fldasn(np, flags)
  411. register NODEP np;
  412. {
  413.     int how;
  414.  
  415.     how = 1;
  416.     if (np->g_fldo == 0)
  417.         how = 0;    /* no shift needed */
  418.     else if (np->g_fldo > 8)
  419.         how = 2;    /* shift too big for immediate */
  420.  
  421.     retreg(np, ralloc(0));
  422.  
  423.     tempr(np, 0);
  424.  
  425.     addcode(np, "\tmove\t>A,A\n");        /* value */
  426.     if (needmask(np))        /* mask off high bits */
  427.         addcode(np, "\tand\t#W,A\n");
  428.     if (how)    /* shift into position */
  429.         addcode(np, how==1 ?    "\tlsl\t#Y,A\n" :
  430.                     "\tlsl\t#8,A\n\tlsl\t#Z,A\n");
  431.  
  432.     addcode(np, "\tmove\t<A,R1\n");        /* old value */
  433.     addcode(np, "\tand\t#X,R1\n");        /* mask out old value */
  434.     addcode(np, "\tor\tA,R1\n");        /* set new field */
  435.     addcode(np, "\tmove\tR1,<A\n");        /* store new word */
  436.  
  437.     if (how && (flags & NOVAL_OK) == 0)    /* return value */
  438.         addcode(np, how==1 ?    "\tlsr\t#Y,A\n" :
  439.                     "\tlsr\t#8,A\n\tlsr\t#Z,A\n");
  440.  
  441.     return OKAY;
  442. }
  443.  
  444. needmask(np)
  445. register NODEP np;
  446. {
  447.     NODEP lp = np->n_left;
  448.  
  449.     if (np->g_fldw + np->g_fldo >= 16)
  450.         return 0;
  451.  
  452.     if (lp->g_token != ICON)
  453.         return 1;
  454.     if ((int)lp->g_offs & ~ones(np->g_fldw)) {
  455.         warn("value too big for field");
  456.         return 1;
  457.     }
  458.     return 0;
  459. }
  460.